pimpas.Validate = Class.create( );

pimpas.Extends(pimpas.Validate, pimpas.Object);

pimpas.Validate.Message = Class.create( );
pimpas.Extends(pimpas.Validate.Message.prototype, pimpas.Object);
pimpas.Extends(pimpas.Validate.Message.prototype,
	{
		level: null,
		message: null,
		obj: null,
		time: null,
		initialize: function(level, obj, message) {
			this.level = level;
			this.obj = obj;
			this.message = message;
			this.id = pimpas.globalID++;
			this.log = new pimpas.Log();
			this.time = new Date();
		}
	}
);

pimpas.Validate.Result = Class.create( );
pimpas.Extends(pimpas.Validate.Result.prototype, pimpas.Object);
pimpas.Extends(pimpas.Validate.Result.prototype,
	{
		initialize: function() {
			this.id = pimpas.globalID++;
			this.log = new pimpas.Log();
			this.messages = new Array();	
		},
		messages: null,
		addMessage: function(m) {
			if(!(m instanceof pimpas.Validate.Message)) return;
			
			this.messages.push(m);
		},
		getMessages: function( ) {
			return this.messages;	
		},
		byLevel: function(level) {
			var ar = new Array();
			for(var i=0;i<this.messages.length;i++)
				if(this.messages[i].level == level) ar.push(this.messages[i]);
			return ar;
		},
		hasErrors: function( ) {
			return this.byLevel(pimpas.Validate.level.ERROR).length>0;	
		},
		hasInfos: function( ) {
			return this.byLevel(pimpas.Validate.level.INFO).length>0;	
		},
		hasWarns: function( ) {
			return this.byLevel(pimpas.Validate.level.WARN).length>0;	
		}
	}
);

pimpas.Extends(pimpas.Validate,
   {
	   events:
	   		{
				onValidate: "onValidate"
			}
		,
		level: 
			{
				WARN: "warn",
				ERROR: "error",
				INFO: "info"
			}
		,
		validate: function( objs, listeners ) {
			var el = null;
			this.log.info("Invoking validate method for ["+objs+"]");
			var result = new pimpas.Validate.Result( );
			for(var i=0;i<objs.length;i++) {
				el = pimpas.DOM.getElement( objs[i] );
				if(el == null) {
					this.log.error("Can't find HTML Element with id/name ["+objs[i]+"], exception.");
					throw new ObjNotFoundException(objs[i]);
				}
				this.log.debug("[Invoking validate listeners for object {"+objs[i]+"}]");
				for(var j=0;j<listeners.length;j++) {
					this.log.debug("[Invoking listener {"+listeners[j]+"} for object {"+objs[i]+"}]");
					this.callListener(pimpas.Validate.events.onValidate, listeners[j], result, el, pimpas.DOM.getObjectValue( el ));
				}
			}
			
			this.log.info("Validate Method Finished! Returning ValidationResult ["+result+"]");
			this.log.debug("[ValidationResult]: Errors? "+result.byLevel(pimpas.Validate.level.ERROR).length+", Warns? "+result.byLevel(pimpas.Validate.level.WARN).length+", Infos? "+result.byLevel(pimpas.Validate.level.INFO).length);
			return result;
		},
		callListener: function(evt, listener, result, obj, value) {
			listener.callBack.bind(listener, evt, obj, value, result)();
			return evt;
		}
   }
);

ObjNotFoundException = Class.create();
pimpas.Extends(ObjNotFoundException.prototype, pimpas.Object);
pimpas.Extends(ObjNotFoundException.prototype,
			   {
				   obj: null,
				   initialize: function(obj) {
					   this.obj = obj;
					   this.id = pimpas.globalID++;
					   this.log = new pimpas.Log();
				   },
				   toString: function( ) {
						return "ObjNotFoundException => "+this.obj;
				   }
			   }
);

pimpas.Validate.Listener = pimpas.Listener;

pimpas.Validate.initialize( );